 PAG
**********************************
*           SEG1
**********************************

]segnum = #$0100  ;current segment number

 ORG $E0C800  ;RUNS FROM $C800

*************** MESSAGES *************

MSGINVBP
 DFB CR
 ASC "INVALID ADDRESS"
 DFB BEL,CR,EOT

* MESSAGE "BREAK"

MSGBRKPT
 DFB CR
 ASC "BREAKS"
 DFB CR,EOT

MSGHARDB
 DFB CR
 ASC "HARDWARE BREAK"
 DFB CR,EOT

MSGAVAIL
 ASC "M or ?"
 DFB 05
 ASC "MENU"
 DFB 24
 ASC "MD [A]"
 DFB 05
 ASC "Mem Dump"
 DFB CR

 ASC "MO"
 DFB 09
 ASC "Mode"
 DFB 24
 ASC "MW"
 DFB 09
 ASC "Mem Wind"
 DFB CR

 ASC "esc"
 DFB 8
 ASC ": level"
 DFB 21
 ASC "MM [A]"
 DFB 05
 ASC "Mem Mod"
 DFB CR

 ASC "SS A"
 DFB 07
 ASC "Set Switch"
 DFB 18
 ASC "MA [A]"
 DFB 05
 ASC "Mini Assem"
 DFB CR

 ASC "SD T"
 DFB 07
 ASC "Set Disp"
 DFB 20
 ASC "PW"
 DFB 09
 ASC "Prot Wind"
 DFB CR

 ASC "ON"
 DFB 37
 ASC "RT"
 DFB 09
 ASC "Real Time"
 DFB CR

 ASC "OFf"
 DFB 36
 ASC "ST [n]"
 DFB 05
 ASC "Step"
 DFB CR

 DFB EOT

MSGAVAL2

 ASC "KEy"
 DFB 08
 ASC "set"
 DFB 25
 ASC "TR [n]"
 DFB 05
 ASC "Trace"
 DFB CR

 ASC "SB [T A.n]"
 DFB 01
 ASC "Set BRK"
 DFB 21
 ASC "TS A"
 DFB 07
 ASC "Trace w/Sub"
 DFB CR

 ASC "RB A"
 DFB 07
 ASC "Remove BRK"
 DFB 18
 ASC "EX [n]"
 DFB 05
 ASC "Execute"
 DFB CR

 ASC "HB [A]"
 DFB 05
 ASC "Hard Brk"
 DFB 20
 ASC "down"
 DFB 07
 ASC "SKIP"
 DFB CR

 ASC "RH"
 DFB 09
 ASC "Remove HB"
 DFB 19
 ASC "ER"
 DFB 09
 ASC "EX to RTS"
 DFB CR

 ASC "RA"
 DFB 09
 ASC "Remove All"
 DFB 18
 ASC "ET A.A"
 DFB 05
 ASC "EX Time"
 DFB CR

 ASC "Li [A]"
 DFB 05
 ASC "List"
 DFB 24
 ASC "GO [A]"
 DFB 05
 ASC "RUN"
 DFB CR

 ASC "DR"
 DFB 09
 ASC "Disp Reg's"
 DFB 18
 ASC "JS A"
 DFB 07
 ASC "JSR A"
 DFB CR

 ASC "R=n"
 DFB 08
 ASC "REG=n"
 DFB 23
 ASC "** [I,C]"
 DFB 03
 ASC "Monitor"
 DFB CR

 ASC "QUit"
 DFB CR
 DFB EOT

MSGREAL DFB CR
 ASC "REAL BRKS IN"
 DFB BEL
 DFB EOT

*-------------------------------------------------
* Conditional register offset table
* Reg, offset
CregOFF db "A",0
 db "X",2
 db "Y",4
 db "S",6
 db "D",8
 db "B",$A
 db "M",$B
 db "Q",$C
 db "P",$D

* Conditional symbol offset table
* Symbol, offset to proper branch routine
CsymOFF db "=",condEQ-condBRKS
 db "<",condLT-condBRKS
 db "]",condGE-condBRKS
 db "#",condNE-condBRKS
 db ">",condGT-condBRKS
 db "[",condLE-condBRKS


*********************************************
*  MAKE SURE THIS POINT IS $CA00 OR HIGHER  *
*********************************************

 ERR *-1/$E0CA00
 DS $E0CA00-*,$FF

* COME HERE FROM LOWER 2K
* MAKE SURE THAT THE INSTRUCTIONS DO NOT BEGIN UNTIL $CA00.

********************************
*  COMDSB - SET BREAK
********************************

* SB (TYPE) (LOCATION)  .  (# OF TIME TO PASS)
* SB   R      01/2003   .   1000
*         LETTER 3,2,1  .   LETTER 6,5,4
* If no bank is specified then break is put in current MEMPBR

COMDSB EQU *
 BNE :SBcont
 JMP BKPDIS ;IF NO DISPLAY BREAKPOINTS
:SBcont CMP #"R" ;if Real
 BEQ :TYPEOK
 CMP #"I" ;if Implied
 BEQ :TYPEOK
 CMP #"C" ; if Conditional
 BEQ :TYPEOK
 LDA #"R" ;DEFAULT TO REAL
 DEY  ;PUT POINTERS BACK TO
 INX  ;.. LAST CHAR
:TYPEOK STA SBTYPE ;SAVE TYPE
 JSR CHKREADA ;read address & count for breakpoint
 BCS :TOBP1C  ;IF NOT HEX

:ADDRSOK BIT ADDRS2F  ;2 NUMBERS INPUT ?
 BMI :TWO  ;IF YES
 LDA SBTYPE
 CMP #"C" ;is this Conditional break?
 BNE :NOTCOND

* Conditional break! Get register, condition & comparison values & setup BRK.
 JSR GETCHR ;get conditional register
 PHX  ; buffer size
 LDX #16
 CMP $C800 ; disable DDT RAM
:repeat CMP CregOFF,X ;search table for matching register
 BNE :nextCrg
 LDA CregOFF+1,X ;get register offset
 CMP $CF00 ; enable DDT RAM
 STA LETTER8
 BRA :CONDsym
:nextCrg DEX
 DEX
 BPL :repeat
:TOBP1CX PLX  ; restore stack
:TOBP1C CMP $CF00 ; enable DDT RAM
 JMP BPERR1 ;Bad Parameters error

:CONDsym PLX  ; restore buffer size
 JSR GETCHR ; get conditional symbol
 PHX  ; save buffer size
 LDX #10
 CMP $C800 ; disable DDT RAM
:repeat2 CMP CsymOFF,X ;search table for matching symbol
 BNE :nextCsy
 LDA CsymOFF+1,X ;get symbol offset
 CMP $CF00 ; enable DDT RAM
 STA LETTER7
 BRA :CONDcmp
:nextCsy DEX
 DEX
 BPL :repeat2
 BRA :TOBP1CX

:CONDcmp PLX  ; restore buffer size
 LDA #$FF
 STA ADDRS2F ; set for 2 number input
 JSR SWAPnext ; read Conditional compare value
 BCS :TOBP1C ; IF NOT valid
 BRA :TWO

:NOTCOND STZ LETTER5  ;
 LDA #1
 STA LETTER4  ;DEFAULT TO 1 ON # OF TIMES TO PASS
:TWO LDA POINT  ;SEE IF THERE IS ROOM FOR ANOTHER BREAK
 CMP #50  ;50 BREAKS
 BLT NOTFULL  ;IF OK
 LDA #BRKFUL  ;ERROR NUMBER
SBERR JMP ERREXIT1 ;NO ROOM
NOTFULL JSR TRANSFR1 ;PUT BRK & UPDATE BRK STACK (Z=0 NOT RAM)
 DFB PUTBREAKC ;CODE
 BEQ ISRAM  ;LOCATION IS RAM
NOTRAM JSR TRANSFR1 ;DISPLAY MESSAGE
 DFB DISNOTRMC ;CODE
ISRAM JSR TRANSFR1 ;UPDATE BRK WINDOW
 DFB DISBRKWC ;code
 JSR TRANSFR1 ;UPDATE FLAG WINDOW
 DFB DISFLGWC ;code
SETDRW JSR TRANSFR1 ;SET DR WINDOW
 DFB WINDDRC  ;code
 BRA ENDSTDR
BKPDIS JSR DISBKP  ;DISPLAY BREAKPOINTS
ENDSTDR JMP GETCOM1

********************************
*  COMDHB - SET HARDWARE BREAK
********************************

COMDHB EQU *
 BEQ SHDIS  ;NOTHING THERE SO DISPLAY BREAKPOINTS

 CMP #"X"  ;stop in all banks?
 BEQ :HALT_AL ;If yes
 LDA #0  ;Default to one bank
 DEY   ;Put pointers back to
 INX   ;.. last character
:HALT_AL
 STA HALT_ALL ;set flag, if >= $80 then stop in all banks

 JSR CHKREADA ;check for hex and read
TOBP1A BCS TOBP1B  ;IF ERROR
 STA VIAORA  ;STORE IN LOW BYTE OF COMPARATOR
 LDA LETTER2  ;GET HI BYTE
 STA VIAORB  ;STORE IN HI BYTE
 LDA LETTER3
 STA HARDPBR  ;BANK TO STOP IN
 LDA #%10010000
 ORA IERBUFF  ;ENABLE HARDWARE BREAK
 STA IERBUFF
 BNE NODISH
SHDIS JSR DISHB  ;DISPLAY HARDWARE BREAK
NODISH BRA ISRAM  ;UPDATE BRK WINDOW	

********************************
*  COMDRB - REMOVE BREAK
********************************

* RB 012003

COMDRB EQU *
 BNE RBOK  ;IF ADDRESS FOLLOWS
TOBP1B JMP BPERR1  ;BAD PARAMETER ERROR
RBOK JSR CHKREAD  ;READ ADDRS INTO LETTER 3,2,1
 BCS TOBP1B  ;IF NOT HEX
 JSR TRANSFR1 ;SEE IF ADDRESS IS ON LIST
 DFB VALIDADC ;code
 BMI INVBREAK ;INVALID BREAKPOINT

* The following subroutine replaces a breakpoint in the program
* with the original data. Removes from BREAKS buffer, and
* reorganizes the breaks list. Enter with Y pointing at the BRK.

 JSR TRANSFR1 ;REPLACE BRK WITH ORIG DATA
 DFB REPLACEC ;code
 BRA ISRAM  ;UPDATE BRK WINDOW

INVBREAK JSR DISINVBP ;DISPLAY "INVALID BRK ADDRS"
RBTOM11 BRA ENDSTDR ;goes to GETCOM1

********************************
*  COMDRH - REMOVE HARDWARE BREAK
********************************

COMDRH JSR CLRHARD  ;CLEAR HARDWARE BREAK
 BRA ISRAM  ;UPDATE BRK WINDOW

********************************
*  COMDRA - REMOVE ALL BREAKS
********************************

COMDRA JSR CLEARALL ;REPLACE ALL BREAKPOINTS WITH ORIGINAL DATA
 BRA ISRAM  ;UPDATE BRK WINDOW

********************************
*  COMDMM - MEMORY MODIFY
********************************

COMDMM EQU *
 BEQ :MMNOADD ;IF NO ADDRESS FOLLOWS
 JSR TRANSFR1 ;GET ADDRESS
 DFB LOADMEMC ;CODE
 BCS BPERR1
:MMNOADD
 JSR DSMEMCOL ;DISPLAY MEM POINTER :
 LDY #0
 JSR SPCBYTE  ;DISPLAY SPACE, BYTE
 LDA #$A0
 JSR TRANSFR1 ;SPACE
 DFB COUTC  ;code
 JSR TRANSFR1 ;READ NEXT CHARACTER
 DFB RDCHARC  ;CODE
 CMP #UPARROW
 BEQ :MMDECP  ;IF UP ARROW
 CMP #DNARROW
 BEQ :INCWCR  ;IF DOWN ARROW
 CMP #CR  ;IS IT RETURN
 BEQ :INCWCR  ;IF YES GO TO NEXT ADDR
 LDX #0
 JSR TRANSFR1 ;GET INPUT NUMBER
 DFB GETLNNOC ;code
 BCS RBTOM11  ;<esc> key so return to command level
 INX   ;MAKE X > 0
 LDY #0  ;FIRST CHAR
 JSR CHKREADA ;CHECK FOR HEX AND READ
 BCS :MMERR  ;IF NOT HEX
 JSR TRANSFR1 ;INIT LOWADD, STORE ACC, AND VERIFY
 DFB INITMMVC ;CODE
 BEQ :INCPC  ;IF OK
:MMERR JSR TRANSFR1 ;BEEP
 DFB BELLC  ;CODE
 BRA :MMNOADD ;DISPLAY
:INCWCR JSR TRANSFR1
 DFB CROUTC  ;CODE
:INCPC JSR TRANSFR1 ;INCREMENT MEMLOW & MEMHI
 DFB INCMEMLHC ;CODE
 BRA :MMNOADD ;NEXT LOCATAION
:MMDECP JSR TRANSFR1
 DFB CROUTC  ;code
 JSR TRANSFR1
 DFB DECMEMLHC ;code
 BRA :MMNOADD ;GO BACK ONE ADDRESS

********************************
*  COMDMD - MEMORY DISPLAY
********************************

COMDMD EQU *
 BEQ MDNOADDR ;IF NO ADDRESS FOLLOWS
 JSR TRANSFR1 ;GET ADDRESS
 DFB LOADMEMC ;CODE
 BCC MDNOADDR
BPERR1 LDA #BADPAR  ;BAD PARAMETER ERROR NUMBER
ERREXIT1
 JSR TRANSFR1 ;INDICATE ERROR
 DFB ERRBEEPC ;code
 BRA MTOM10 ;goes to GETCOM1
MDNOADDR
 JSR TRANSFR1 ;FULL SCREEN
 DFB WINDFULC ;CODE
MDAGAIN LDA #16  ;DISPLAY 16 LINES
MDLOOP PHA   ;SAVE
 JSR MEMDISP  ;DISPLAY LINE OF MEMORY
 CLC
 LDA MEMLOW
 ADC #16
 STA MEMLOW
 LDA MEMHI
 ADC #0
 STA MEMHI
 PLA
 SEC
 SBC #1
 BNE MDLOOP
 JSR TRANSFR1 ;"(return/esc)" C=0 on return, C=1 on esc
 DFB WAITCRC  ;code
 BCS WINDM10
 BCC MDAGAIN  ;do another screen full

********************************
*  COMDM - MENU
********************************

CMDMENU
 JSR TRANSFR1 ;FULL SCREEN
 DFB WINDFULC ;CODE
 PEA MSGAVAIL ;message location
 JSR WRITE1  ;display it

* MAX MESSAGE LENGTH IS 256 BYTES

 PEA MSGAVAL2 ;message location
 JSR WRITE1  ;display it

 JSR TRANSFR1 ;"(return/esc)" C=0 on return, C=1 on esc
 DFB WAITCRC  ;code
WINDM10 JSR TRANSFR1 ;redisplay windows
 DFB DISPONC  ;code

MTOM10 JMP GETCOM1

******************************
*  COMDQU - QUIT
******************************

* Allows entering DDT as a subroutine, doing your
* debugging and returning to your program.
* RESTORE ALL REGISTERS, DISABLE VIA, DO AN RTS BACK TO USER

COMDQU SEC ;indicate "QU" command
 CLV ;cloaking device off
 BRA ASTAST

*-------------------------------------------------
*  COMD** [I,C] -
*  **   - Enter Monitor, ^Y vector enabled, interrupts enabled
*  ** I - Enter Monitor, ^Y vector enabled, interrupts disabled
*  ** C - Enter Monitor, Cloaking device on, ^Y off, interrupts disabled
*-------------------------------------------------

COMDDAST CLV  ;assume Cloaking device off
 BEQ :NOOPT ;if no option given, command was "** "
 CMP #"I" ;interrupts disabled?
 BEQ :OPTI ;if yes, command was "** I"
 CMP #"C" ;Cloaking device on?
 BNE BPERR1 ;if no, bad parameter

* command was "** C"
 SEP #$40 ;V=1, Cloaking device on

:OPTI LDA #$04
 TSB STATUS ;disable interrupts
 LDA #$08 ;clear Decimal flag
 BRA :SETSTAT
:NOOPT LDA #$0C ;clear Decimal, enable Interrupts
:SETSTAT TRB STATUS ;set status

 CLC  ;indicate "**" command

* DISABLE VIA, RESTORE INT VECTORS, GOTO MONITOR

ASTAST PHP   ;SAVE CARRY & V

 LDA REALBRK  ;ANY REAL BRKS IN
 BEQ :NOREALS ;IF NO

* DISPLAY WARNING MESSAGE
 PEA MSGREAL  ;message location
 JSR WRITE1  ;display it

 JSR TRANSFR1 ;"(return/esc)" C=0 on return, C=1 on esc
 DFB WAITCRC  ;code
 BCC :NOREALS
 PLA   ;clean up stack
 BRA MTOM10  ;cancel command

:NOREALS
 JSR TRANSFR1 ;RESTORE APPLE RAM
 DFB RESTSTUFC ;CODE
 LDA #$FF
 STA VIAIFR
 LDA #%10000010 ;ENABLE ONLY BUTTON
 STA VIAIER

 PLP   ;GET CARRY FLAG
 INDEX16
 LDX #DDTSTACK ;USE DDT STACK SPACE
 TXS
 PHP   ;SAVE CARRY
 JSR TRANSFR1 ;RESTORE WORK STACK SPACE
 DFB WSTKRESC ;code

 PLP   ;GET SAVED C & V
 LDX STACK  ;USE THIS STACK LOCATION
 TXS

* IF LEAVING WITH "**" COMMAND, DISABLE WRITING TO CARD
 LDA #%11011100 ;CB2 LOW, CB1 POS EDGE, CA2 LOW, CA1 NEG EDGE
 BVS :SETVIA
 LDA #%11011110 ;WRITING TO CARD IS OK with "*" & "QU"
:SETVIA STA VIAPCR

 LDA #0
 PHA
 PLB  ;SET DBR TO 0

 BCS :DORTS ;COMMAND WAS QUIT
 BVS :NOCTRLY ;Cloaking device is on so don't enable ^Y vector

* Cloaking device off so enable ^Y vector to return to DDT
 LDY #2 ;3 bytes in ^Y vector
:REPEAT LDA $03F8,Y ;get user's ^Y vector
 STA DDT3F8,Y ;save in DDT ram
 LDA :DDTCTRLY,Y ;get DDT vector
 STA $03F8,Y ;put in GS ^Y vector
 DEY
 BPL :REPEAT ;do 3 bytes
 LDA SLOTCN ;set ^Y vector for current DDT slot
 STA $03FA

:NOCTRLY LDA #^MONITOR ;bank of routine
 LDX #MONITOR-1 ;address of Apple monitor routine
 SEC  ;set 6502 mode
 BRA :TOPLP

* load this jump into GS ^Y vector
:DDTCTRLY JMP WARMENTR ;^Y jumps to warm entry

*-------------------------------------------------
* RETURN TO USER

:DORTS ROL EMULATE ;set C with Emulation bit

 LDA PBR ;user's program bank
 LDX RET_ADD ;GET USER'S RETURN ADDRESS

* go to our slot space to do PLP, RTL incase interrupts are pending.
:TOPLP PHA
 PHX   ;user's return address
 XCE   ;set mode
 LDX XREG
 LDY YREG
 LDA STATUS
 PHA
 LDA SLOTCN
 PHA
 LDA #SLOTPLP
 PHA
 RTS  ;go to SLOTPLP routine

*----------------------*
*   Command Li - LIST
*----------------------*

COMDLI EQU *
 BEQ LIST ;IF NO ADDRESS FOLLOWS
 JSR TRANSFR1 ;GET ADDRESS
 DFB LOADMEMC ;CODE
 BCC LIST
 JMP BPERR1 ; BAD PARAETER

***** Disassemble and list 20 lines of the program

LIST LDA #20 ;20 LINES
:NEXT PHA ;SAVE

* on return NUMDISP = # of bytes in isntruction - 1

 JSR TRANSFR1 ;LIST 1 LINE
 DFB DISASMC ;code
 SEC
 LDA NUMDISP
 ADC MEMLOW
 STA MEMLOW
 LDA MEMHI ;INC MEMORY POINTER
 ADC #0
 STA MEMHI
 PLA
 SEC
 SBC #1 ;DECREMENT COUNTER
 BEQ :END ;IF FINISHED
 LDX MLIFLAG ;WAS THE LAST INST. AN MLI CALL
 BNE :NEXT ;IF NO
 SBC #1 ;COMPENSATE FOR XTRA LINE OF MLI
 BNE :NEXT
:END JMP GETCOM1


*-------------------------------------------------
*  SUBROUTINES
*-------------------------------------------------

* CLEAR ALL OF THE BREAKPOINTS

CLEARALL LDY POINT  ;GET POINTER
 BEQ CLRHARD  ;BP'S ALL GONE
 DEY   ;POINT AT BRL
 JSR TRANSFR1 ;REPLACE BRK WITH ORIG DATA
 DFB REPLACEC
 JMP CLEARALL ;LOOP UNTIL DONE
CLRHARD LDA #%11101111 ;DISABLE HARDWARE BREAK
 AND IERBUFF  ;SET IER FLAG FOR HARDWARE BREAK TO ZERO (CA1)
 STA IERBUFF
 RTS

*-------------------------------------------------
* DISPLAY ONE LINE OF MEMORY

MEMDISP EQU *
 JSR DSMEMCOL ;DISPLAY MEMORY POINTER
 LDY #00
MMDISHEX
 JSR SPCBYTE  ;DISPLAY SPACE BYTE
 INY
 CPY #16
 BNE MMDISHEX
 LDX #2
 JSR TRANSFR1 ;2 SPACES
 DFB PRBL2C  ;CODE
 LDY #00
MMDISASC
 JSR TRANSFR1 ;LDA LOWADD,Y
 DFB LDAINDYC ;CODE

* Change control codes to normal letters so then don't mess up the display

 ORA #$80  ;FORCE TO NEGATIVE
 CMP #$FF  ;$FF IS NOT ALLOWED
 BEQ MAKEDOT
 CMP #$A0
 BGE MMDISOK
MAKEDOT LDA #"."  ;DISPLAY PERIOD
MMDISOK JSR TRANSFR1
 DFB COUTC  ;CODE
 INY   ;DISPLAY THE ASCII EQUIV
 CPY #16
 BNE MMDISASC
 JSR TRANSFR1 ;RETURN
 DFB CROUTC  ;CODE
 RTS

* Display contents of MEMHI & MEMLOW
* Display user specified bank

DSMEMCOL LDA MEMPBR
 STA DBRDDT ;DATA BANK TO ACCESS
 JSR TRANSFR1 ;PRINT BANK NUMBER
 DFB PRBYTEC  ;CODE
 LDA #"/"
 JSR TRANSFR1
 DFB COUTC  ;CODE
 LDA MEMHI
 STA HIADD
 LDX MEMLOW
 STX LOWADD
 JSR TRANSFR1
 DFB PRNTAXC  ;CODE
 LDA #":"
 JSR TRANSFR1
 DFB COUTC  ;CODE
 RTS

* Display space and LOWADD,Y as hex byte

SPCBYTE LDA #$A0
 JSR TRANSFR1
 DFB COUTC  ;CODE
 JSR TRANSFR1
 DFB LDAINDYC ;CODE
 JSR TRANSFR1
 DFB PRBYTEC  ;CODE
 RTS

* Ignores spaces & returns with Z bit set when buffer empty.

GETCHR LDA IN,Y  ;GET CHARACTER
 INY
 DEX   ;SETS ZFLAG WHEN BUFFER EMPTY
 BEQ EMPTY
 CMP #$A0  ;IS CHARACTER A SPACE
 BEQ GETCHR  ;IGNORE SPACES
EMPTY RTS

* Read in the numbers (default to hex, "!" = decimal)
* Put in (LETTER 3,2,1) OR (LETTER 3,2,1 . LETTER 6,5,4)
* Allow the following as valid $0001, $ 0001, $1, 1, C1B etc.
* C = 1 if no number or invalid character

CHKREAD DEY   ;PUT POINTERS BACK
 INX   ;TO LOOK AT LAST CHARACTER
CHKREADA LDA #0
 STA ADDRS2F  ;CLEAR FLAGS
 STA INLENGTH
READAD2 LDA #0
 STA DTOHFLG ;DEFAULT TO HEX
 JSR CLRLETER ;CLEAR LETTER 1,2,3
SKIPDLR JSR GETCHR ;GET NEXT CHAR (IGNORE SPACES)
 BEQ CKRDERR ;ERROR
 CMP #"$" ;IS CHAR A DOLLAR SIGN
 BEQ SKIPDLR ;IF YES
 CMP #"!" ;DECIMAL NUMBER ?
 BNE READAD ;IF NO
 STA DTOHFLG ;IF YES, SET DEC TO HEX FLAG
 BEQ SKIPDLR

* Read address in, convert to hex, store in LETTER 1,2,3
* INLENGTH contains number of digits read

READAD CMP #$B0  ;IS IT < "0"
 BLT CKRDERR  ;IF YES
 CMP #$BA
 BLT ISDEC  ;IS 0-9
 CMP #$C1  ;COMPARE WITH "A"
 BLT CKRDERR
 CMP #$C7
 BGE CKRDERR
 BIT DTOHFLG  ;SUPPOSED TO BE DECIMAL ?
 BPL ITISHEX  ;IF NO

CKRDERR SEC
 RTS   ;******** ERROR RTS ********

ITISHEX CLC   ;CLEAR CARRY
 ADC #$9  ;ADD 9 TO CONVERT TO A-F
ISDEC AND #$F  ;STRIP MOST SIG. DIGIT
 STY YBUFF
 LDY #4
:SHIFT ASL LETTER1  ; -KEEP SHIFTING IN NEW DIGITS
 ROL LETTER2  ; - FROM THE RIGHT UNTIL
 ROL LETTER3
 DEY   ; - OUT OF DIGITS
 BNE :SHIFT
 ORA LETTER1
 STA LETTER1
 LDY YBUFF  ;RESTORE
 INC INLENGTH
 JSR GETCHR  ;GET NEXT CHAR IF ANY
 BEQ :READEND
 CMP #"/"  ;NEW BANK ?
 BNE :CHKPER  ;IF NO
 BIT DTOHFLG  ;CONVERT TO HEX ?
 BPL :INHEX  ;IF NO
 JSR DECHEX  ;CONVERT
:INHEX LDA LETTER1
 STA MEMPBR  ;NEW PBR
 SEC
 ROR BANKENT  ;indicate bank number was entered
 JMP READAD2
:CHKPER CMP #"."  ;PERIOD MEANS SECOND NUMBER
 BEQ ADDRS2  ;READ SECOND NUMBER
 CMP #"]"
 BEQ :READEND
 CMP #")"
 BEQ :READEND
 CMP #","  ;USE COMMA AS DELIMITER
 BNE READAD
:READEND
 BIT DTOHFLG  ;CONVERT DEC TO HEX ?
 BPL :INHEX2  ;IF NO
 JSR DECHEX  ;CONVERT
:INHEX2 BIT ADDRS2F  ;2 NUMBERS ENTERED ?
 BPL SETBANK  ;IF NO
 JSR SWAPLET  ;IF YES, SWAP LETTERS

SETBANK ASL BANKENT  ;was a bank number entered?
 BCS :SET  ;if yes
 LDA INLENGTH ;quantity of digits input
 CMP #5  ;was BANK specified ?
 BGE :YES  ;if yes
:SET LDA MEMPBR
 STA LETTER3  ;default to current MEMPBR
:YES LDA LETTER1
 CLC
 RTS   ;RETURN WHEN OUT OF CHARACTERS

* Transfer LETTER 3,2,1 TO LETTER 6,5,4
* Read second number into LETTER 3,2,1

ADDRS2 STA ADDRS2F ;SET 2 ADDRESS FLAG
 BIT DTOHFLG ;CONVERT DEC TO HEX ?
 BPL SWAPnext ;IF NO
 JSR DECHEX ;CONVERT
SWAPnext JSR SWAPLET ;SWAP LETTER 1,2,3 WITH LETTER 4,5,6
 JMP READAD2 ;READ NEXT NUMBER

*---------------------------------
* Write text to the display device
* The address of the text is on the stack
* Positive numbers are RLE compressed spaces

* This routine must be above $CF00

WRITE1 STY YBUFF  ;SAVE
 LDY #0
WRITLOP1 CMP $C800  ;disable DDT RAM
 LDA (3,S),Y  ;get character to display
 CMP $CF00  ;enable DDT RAM
 INY   ;next character
 CMP #EOT  ;finished?
 BEQ :DONE  ;if yes
 AND #$FF  ;SET FLAGS
 BPL :SPACES  ;if compressed spaces

 JSR TRANSFR1 ;display character
 DFB COUTC  ;code
 BRA WRITLOP1 ;loop until done

:SPACES TAX
 JSR TRANSFR1 ;PRINT SPACES
 DFB PRBL2C  ;code
 BRA WRITLOP1 ;loop until done

:DONE MEMORY16
 PLA   ;get return address
 STA 1,S  ;free parameter space
 MEMORY8
 LDY YBUFF  ;RESTORE
 RTS

*-------------------------------------------------
* Display the breakpoints

DISBKP PEA MSGBRKPT ;message location
 JSR WRITE1  ;display it

 LDY POINT  ;GET BREAKPOINT BUFFER POINTER
 BEQ :DSEND  ;ALL DONE
 LDX #2
:DISNEXT
 DEY
 TXA
 PHA   ;SAVE X
 JSR DSPBRK
 PLA
 TAX   ;RESTORE X
 DEX   ;END OF ROW?
 BNE :SPC  ;IF NO
 LDX #2  ;2 BRKS PER ROW
 LDA #CR ; <cr>
 BNE :NOSPC
:SPC LDA #$A0 ; SPACE
:NOSPC JSR TRANSFR1 ; display it
 DFB COUTC  ;code
:NOTSER CPY #0
 BNE :DISNEXT
:DSEND RTS

***** Display the breakpoint info pointed to by Y *****

DSPBRK LDX SLOTN0
****************************************
* !!! ALERT !!! SEGMENT DEPENDENT CODE *
****************************************
 LDA #%01100001 ;RAM6, ROM1
 STA SEGMBASE,X
 LDA BRKPASLO,Y ; used by conditional break display
 PHA
 LDA BRKPASHI,Y ; "
 PHA
 LDA BRKTGLOW,Y
 PHA
 LDA BRKTGHI,Y
 PHA
 LDA BRKLOW,Y
 PHA
 LDA BRKHI,Y
 PHA
 LDA BRKPBR,Y
 PHA
 LDA BRKTYPE,Y
 PHA
****************************************
* !!! ALERT !!! SEGMENT DEPENDENT CODE *
****************************************
 LDA #%00000001 ;RAM0, ROM1
 STA SEGMBASE,X
 PLA
 STA TEMP ; save BRK type
 JSR TRANSFR1 ;PRINT TYPE
 DFB COUTC  ;code
 PLA
 JSR TRANSFR1 ;PRINT BANK NUMBER
 DFB PRBYTEC  ;code
 LDA #"/"
 JSR TRANSFR1
 DFB COUTC  ;code
 PLA
 JSR TRANSFR1 ;PRINT ADDRS
 DFB PRBYTEC  ;code
 PLA
 JSR TRANSFR1
 DFB PRBYTEC  ;code

 LDA TEMP ; get break type
 CMP #"C" ; is it conditional break?
 BNE :NOTCOND ; if no
 PLA ; get conditional register offset
 LDX #$10
 CMP $C800 ; disable DDT RAM
:REPEAT CMP CregOFF+1,X ; look for register offset in table
 BNE :NEXToff ; if no match
 LDA CregOFF,X ; get conditional register ASCII value
 BRA :gotREG
:NEXToff DEX
 DEX
 BPL :REPEAT ; keep looking
:gotREG CMP $CF00 ; enable DDT RAM
 JSR TRANSFR1 ; PRINT cond register
 DFB COUTC ; code

 PLA  ; get conditional symbol offset
 LDX #$A
 CMP $C800 ; disable DDT RAM
:REPEAT2 CMP CsymOFF+1,X ; look for matching offset in table
 BNE :NEXTsym ; if no match
 LDA CsymOFF,X ; get conditional symbol ASCII value
 BRA :gotSYM
:NEXTsym DEX
 DEX
 BPL :REPEAT2
:gotSYM CMP $CF00 ; enable DDT RAM
 JSR TRANSFR1 ; print cond symbol
 DFB COUTC ; code
 BRA :CNDcont

:NOTCOND LDA #"."
 JSR TRANSFR1 ;PRINT "."
 DFB COUTC  ;code
 MX16
 PLA
 PLX  ; remove conditional stuff from top of stack
 PHA
 MX8

:CNDcont PLA
 JSR TRANSFR1 ;PRINT NUMBER
 DFB PRBYTEC  ;code
 PLA
 JSR TRANSFR1
 DFB PRBYTEC  ;code
 RTS

DISHB PEA MSGHARDB ;message location
 JSR WRITE1  ;display it

 JSR TRANSFR1 ; finish displaying hardware break
 DFB DSPHBPC ; code
 RTS


***** MUST BE ABOVE $CF00 *****
* Display invalid breakpoint message

DISINVBP PEA MSGINVBP ;message location
 JSR WRITE1  ;display it
 RTS

*----------------------------------------
*  GETCOM1 - do <CR> & get user command

GETCOM1 PEA GETCOMCR-1 ;address of command
 PEA S_GETCOM ;segment of command
 JMP JUMPSEG1 ;go to command

*-------------------------------------------------
** Convert the decimal number in LETTER 3,2,1 to hex

DECHEX STX XBUFF
 LDX #2
:LOADDEC
 LDA LETTER1,X ;LETTER 1,2,3 TO
 STA DECIMAL1,X ;DECIMAL 1,2,3
 DEX
 BPL :LOADDEC
 JSR CLRLETER ;LETTER 1,2,3 TO 0
 LDX DECIMAL3 ;M.S. 2 DIGITS
 BEQ :TRYDEC2
:DEC3 LDA #$10  ;ADD 10,000 DEC
 JSR ADDL1  ;
 LDA #$27  ;IN HEX FORM $2710
 CLC
 JSR ADDL2
 JSR SUBD1
 BNE :DEC3  ;MORE 10,000
:TRYDEC2
 LDX DECIMAL2
 BEQ :TRYDEC1
:DEC2 LDA #$64
 JSR ADDL1
 JSR SUBD1
 BNE :DEC2
:TRYDEC1
 LDX DECIMAL1
 BEQ DHRTS
:DEC1 LDA #1
 JSR ADDL1
 JSR SUBD1
 BNE :DEC1
DHRTS LDX XBUFF  ;RESTORE
 RTS

ADDL1 CLC
 ADC LETTER1
 STA LETTER1
 LDA #0
ADDL2 ADC LETTER2
 STA LETTER2
 LDA #0
 ADC LETTER3
 STA LETTER3
 RTS

SUBD1 TXA
 SED
 SEC
 SBC #1
 CLD
 TAX
 RTS

CLRLETER LDA #0
 STA LETTER1
 STA LETTER2
 STA LETTER3
 RTS

* Swap LETTER 1,2,3 with LETTER 4,5,6

SWAPLET JSR SETBANK  ;set letter3 to MEMPBR if bank was entered
 STX XBUFF
 STY YBUFF
 LDX #2
:SWAP LDA LETTER1,X
 LDY LETTER4,X
 STA LETTER4,X
 TYA
 STA LETTER1,X
 DEX
 BPL :SWAP
 LDY YBUFF
 LDX XBUFF
 RTS

***** GLOBAL SUBROUTINES IN THIS SEGMENT *****

SUBTABL1

GETCHRC EQU *-SUBTABL1*4+1+$100
 DA GETCHR-1

CHKREADC EQU *-SUBTABL1*4+1+$100
 DA CHKREAD-1

CHKREADAC EQU *-SUBTABL1*4+1+$100
 DA CHKREADA-1

DSMEMCOLC EQU *-SUBTABL1*4+1+$100
 DA DSMEMCOL-1

DSPBRKC EQU *-SUBTABL1*4+1+$100
 DA DSPBRK-1

*****************************************
*  SEGMENT CROSSOVER AREA  *
*****************************************

 LST ON
S1END = $E0CF91-*
 do nolist
 LST OFF
 fin
 ERR *-1/$E0CF91
 DS $E0CF91-*,$FF

******** SAVE THE ACC, X, Y AND P REGISTERS *******
* Returns with MX = 11, saves registers

SAVEAXP1
 PHP   ;SAVE STATUS
 MX16
 STX XSAVESEG ;save 16 bits
 STY YSAVESEG ;save 16 bits
 STA ASAVESEG ;save 16 bits
 MX8
 PLA   ;GET STATUS
 STA PSAVESEG ;SAVE
 RTS

****** RESTORE THE ACC, X, Y AND P REGISTERS ******
* restores registers

RESTAXP1
 MEMORY8
 LDA PSAVESEG
 PHA
 MX16
 LDX XSAVESEG
 LDY YSAVESEG
 LDA ASAVESEG
 PLP
 RTS
 MX %11

*----------------------------------------
* Do a direct transfer to other segments

JUMPSEG1
 JSR SAVEAXP1
 LDY SLOTN0
 PLA   ;pull junk byte from dest. seg
 PLA   ;get destination segment
 STA SEGMBASE,Y ;the next inst' will be in new seg
 JSR RESTAXP1 ;restore after xfer from other seg
 RTS   ;pull destination address from stack

* TRANSFER TO OTHER SEGMENTS

TRANSFR1
 JSR SAVEAXP1
 MEMORY16
 PLA   ;get return address from stack
 INC   ;inc to point at code byte & for RTS
 PHA
 MEMORY8
 LDA #1  ;CURRENT SEG #
 PHA
 LDY #0
 LDA (2,S),Y  ;GET CODE BYTE
 PHA   ;SAVE CODE
 AND #$07  ;STRIP ALL BUT SEG #
 LDY SLOTN0
 STA SEGMBASE,Y ;NEXT INSTR. RUN FROM NEW SEGMENT
* NEW SEGMENT
 PLA   ;GET CODE
 PEA RETURN1  ;where to return to
 AND #$F8  ;STIP OFF SEG# LEAVING SUB #
 LSR
 LSR   ;LEAVE SUB# MULTIPLIED BY 2
* GET ADDRESS OF SUB FROM SUBTABL & PUSH ON STACK
 TAY
 MEMORY16
 LDA SUBTABL1,Y
 PHA
 BRA RESTAXP1 ;RESTORE REGISTERS, RTS TO SUBROUTINE
 MX %11

* RETURN HERE FROM SUBROUTINE

RETURN1 EQU *-1
 JSR SAVEAXP1
 PLA   ;SEG # TO RETURN TO
 LDY SLOTN0
 STA SEGMBASE,Y ;RETURN TO SEGMENT
 BRA RESTAXP1

 DS \,$FF  ;PUT OBJECT AT NEXT PAGE
